using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Woz
{
    /// <summary>
    /// the action that selects or deselects entities on the screen
    /// </summary>
    internal class SelectAction : Woz.Action
    {
        /// <summary>
        /// creates a select action that will deselect the old selected entities and selects the new selected entities
        /// </summary>
        /// <param name="pScreen">the screen were selecting or deselecting from</param>
        /// <param name="pOldSelectedEntities">the old selected entities or what to deselect</param>
        /// <param name="pNewSelectedEntities">the new selected entities or what to select</param>
        public SelectAction(Woz.Screen pScreen, Woz.Entity[] pOldSelectedEntities, Woz.Entity[] pNewSelectedEntities)
        {
            // set the screen
            this.mScreen = pScreen;

            // set the old selected entities
            this.mOldSelectedEntities = pOldSelectedEntities;

            // set the new selected entities
            this.mNewSelectedEntities = pNewSelectedEntities;
        }

        /// <summary>
        /// gets the name of the tool this action prefers
        /// </summary>
        public override string ToolName
        {
            get
            {
                return "Select";
            }
        }

        /// <summary>
        /// gets whether this action can be propagated or not
        /// </summary>
        public override bool Propagatable
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// selects the newselectedentities and deselects the oldselectedenetities
        /// </summary>
        /// <param name="pScreen">not used for non propagateable action</param>
        protected override void OnExecute(Woz.Screen pScreen)
        {
            // deselect the old selected entities
            foreach (Woz.Entity entity in this.mOldSelectedEntities)
            {
                this.mScreen.DeselectEntity(entity, false);
            }

            // select the new selected entities
            foreach (Woz.Entity entity in this.mNewSelectedEntities)
            {
                this.mScreen.SelectEntity(entity, false);
            }

            // compute the union of bounding box of the old selected entities and new selected entities
            Rectangle selectionRect = Rectangle.Union(
                Woz.Entity.ComputeBoundingBox(this.mOldSelectedEntities),
                Woz.Entity.ComputeBoundingBox(this.mNewSelectedEntities));

            // inflate it by ten pixels to account for the selection
            selectionRect.Inflate(Woz.InkSpaceConverter.Instance.InkSpaceTenPixels,
                Woz.InkSpaceConverter.Instance.InkSpaceTenPixels);

            // request an update from the selected screen
            Woz.ScreenManager.Instance.RequestSelectedScreenUpdate(pScreen, selectionRect);
        }

        /// <summary>
        /// selects the oldselectedentities and deselects the newselectedenetities
        /// </summary>
        /// <param name="pScreen">not used for non propagateable action</param>
        protected override void OnUnExecute(Woz.Screen pScreen)
        {
            // deselect the new selected entities
            foreach (Woz.Entity entity in this.mNewSelectedEntities)
            {
                this.mScreen.DeselectEntity(entity, false);
            }

            // select the old selected entities
            foreach (Woz.Entity entity in this.mOldSelectedEntities)
            {
                this.mScreen.SelectEntity(entity, false);
            }

            // compute the union of bounding box of the old selected entities and new selected entities
            Rectangle selectionRect = Rectangle.Union(
                Woz.Entity.ComputeBoundingBox(this.mOldSelectedEntities),
                Woz.Entity.ComputeBoundingBox(this.mNewSelectedEntities));

            // inflate it by ten pixels to account for the selection
            selectionRect.Inflate(Woz.InkSpaceConverter.Instance.InkSpaceTenPixels,
                Woz.InkSpaceConverter.Instance.InkSpaceTenPixels);

            // request an update from the selected screen
            Woz.ScreenManager.Instance.RequestSelectedScreenUpdate(pScreen, selectionRect);
        }

        /// <summary>
        /// an array of the old selected entities
        /// </summary>
        Woz.Entity[] mOldSelectedEntities;

        /// <summary>
        /// an array of the new selected entities
        /// </summary>
        Woz.Entity[] mNewSelectedEntities;
    }
}
